package javaapplication8.Make;

// $Source: /h/u1/szamosi/repo/b07/examples/remake/DirectedGraph.java,v $
// $Date: 2007/06/24 00:25:13 $
// $Revision: 1.1.1.1 $

import java.util.Collection;
import java.util.Set;
import java.util.HashSet;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;

class DirectedGraph {

    // Construct empty graph
    public DirectedGraph() {
        fNodes = new HashMap();
    }
  
    // Get all nodes
    public Set getNodes() {
        return fNodes.keySet();
    }

    // Does this graph contain the specified node?
    public boolean hasNode(Object node) {
        return fNodes.containsKey(node);
    }

    // Add the specified node with no arcs or data
    public void addNode(Object node) {
        addEmptyNode(node);
    }

    // Add a node with arcs and data
    public void addNode(Object node, Collection arcs, Object data) {
        addEmptyNode(node);
        addArcs(node, arcs);
        setData(node, data);
    }

    // Remove a node (along with all arcs and data)
    public void removeNode(Object node) {
        fNodes.remove(node);
        Iterator ni = getNodes().iterator();
        while (ni.hasNext()) {
            removeArc(ni.next(), node);
        }
    }
  
    // Get all arcs out from a node
    public Set getArcs(Object node) {
        return getStorage(node).fArcs;
    }

    // Is there an arc between the specified nodes?
    public boolean hasArc(Object src, Object dst) {
        return getArcs(src).contains(dst);
    }

    // Add an arc between the specified nodes
    // Does nothing if arc already exists
    public void addArc(Object src, Object dst) {
        if (!fNodes.containsKey(dst)) {
            addEmptyNode(dst);
        }
        Set arcSet = getStorage(src).fArcs;
        arcSet.add(dst);
    }

    // Add arcs from source to all specified destinations
    public void addArcs(Object src, Collection allDst) {
        Iterator ia = allDst.iterator();
        while (ia.hasNext()) {
            addArc(src, ia.next());
        }
    }

    // Remove an arc between source and destination; does nothing if arc
    // does not exist
    public void removeArc(Object src, Object dst) {
        Set arcSet = getStorage(src).fArcs;
        if (arcSet.contains(dst)) {
            arcSet.remove(dst);
        }
    }
  
    // Get data associated with a node
    public Object getData(Object node) {
        return getStorage(node).fData;
    }

    // Set data associated with a node; adds the node if it does not
    // already exist
    public void setData(Object node, Object data) {
        if (!fNodes.containsKey(node)) {
            addEmptyNode(node);
        }
        getStorage(node).fData = data;
    }
  
    // Create printable representation of graph
    public String toString() {
        String result = "";
        Iterator in = getNodes().iterator();
        while (in.hasNext()) {
            Object node = in.next();
            result += node.toString() + " {";
            Iterator ia = getArcs(node).iterator();
            while (ia.hasNext()) {
                result += " " + ia.next().toString();
            }
            result += " } (";
            if (getData(node) != null) {
                result += getData(node).toString();
            }
            else {
                result += "-null-";
            }
            result += ")\n";
        }
        return result;
    }

    //------------------------------------------------------------
  
    // Add an empty node
    protected void addEmptyNode(Object node) {
        if (!fNodes.containsKey(node)) {
            fNodes.put(node, new Storage());
        }
    }

    // Get the Storage object associated with a node
    protected Storage getStorage(Object node) {
        return (Storage)fNodes.get(node);
    }
  
    // Store arcs and data for a node
    protected class Storage {
        public Storage() {
            fArcs = new HashSet();
            fData = null;
        }
        Set    fArcs;
        Object fData;
    }

    //------------------------------------------------------------

    protected Map       fNodes;         // nodes -> Storage objects
}
